package com.hh.service.service.impl.merchant;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hh.common.constants.Constants;
import com.hh.common.exception.HhException;
import com.hh.common.model.merchant.MerchantAdmin;
import com.hh.common.model.merchant.MerchantMenu;
import com.hh.common.model.merchant.MerchantMenuInit;
import com.hh.common.request.SystemMenuRequest;
import com.hh.common.request.SystemMenuSearchRequest;
import com.hh.common.utils.RedisUtil;
import com.hh.common.utils.SecurityUtil;
import com.hh.common.vo.MenuCheckTree;
import com.hh.common.vo.MenuCheckVo;
import com.hh.service.dao.merchant.MerchantMenuDao;
import com.hh.service.dao.merchant.MerchantMenuInitDao;
import com.hh.service.service.merchant.MerchantMenuService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class MerchantMenuServiceImpl extends ServiceImpl<MerchantMenuDao, MerchantMenu> implements MerchantMenuService {

    private static final String CACHE_LIST_KEY = "merMenuList:";

    @Autowired
    private RedisUtil redisUtil;

    @Resource
    private MerchantMenuDao dao;

    @Resource
    private MerchantMenuInitDao merchantMenuInitDao;

    @Override
    public List<MerchantMenu> getAllPermissions(String merId) {
        LambdaQueryWrapper<MerchantMenu> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerchantMenu::getMerId,merId);
        lqw.eq(MerchantMenu::getIsDelte, false);
        lqw.ne(MerchantMenu::getMenuType, "M");
        return dao.selectList(lqw);
    }

    @Override
    public List<MerchantMenu> findPermissionByUserId(Integer userId) {
        return dao.findPermissionByUserId(userId);
    }

    @Override
    public List<MerchantMenu> getCacheList(String merId) {
        String cacheKey = CACHE_LIST_KEY + merId;
        if (redisUtil.exists(cacheKey)) {
            List<MerchantMenu> list = redisUtil.get(cacheKey);
            if(list.size() > 0){
                return list;
            }
        }
        LambdaQueryWrapper<MerchantMenu> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerchantMenu::getMerId,merId);
        lqw.eq(MerchantMenu::getIsDelte, false);
        List<MerchantMenu> merchantMenuList = dao.selectList(lqw);
        redisUtil.set(cacheKey, merchantMenuList);
        return merchantMenuList;
    }

    @Override
    public List<MerchantMenu> getAdminList(SystemMenuSearchRequest request) {
        String merId = SecurityUtil.getMerLoginUserVo().getUser().getMerId();

        LambdaQueryWrapper<MerchantMenu> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerchantMenu::getMerId,merId);
        if (StrUtil.isNotEmpty(request.getName())) {
            lqw.like(MerchantMenu::getName, request.getName());
        }
        if (StrUtil.isNotEmpty(request.getMenuType())) {
            lqw.eq(MerchantMenu::getName, request.getMenuType());
        }
        lqw.eq(MerchantMenu::getIsDelte, false);
        lqw.orderByDesc(MerchantMenu::getSort);
        lqw.orderByAsc(MerchantMenu::getId);
        return dao.selectList(lqw);
    }

    @Override
    public Boolean add(SystemMenuRequest request) {
        MerchantAdmin user = SecurityUtil.getMerLoginUserVo().getUser();
        String cacheKey = CACHE_LIST_KEY + user.getMerId();
        if (request.getMenuType().equals("C") && StrUtil.isEmpty(request.getComponent())) {
            throw new HhException("菜单类型的组件路径不能为空");
        }
        if (request.getMenuType().equals("A") && StrUtil.isEmpty(request.getPerms())) {
            throw new HhException("按钮类型的权限表示不能为空");
        }
        if(!Constants.PLATFORM_MER_ID.equals(user.getMerId())){
            throw new HhException("您没有权限操作");
        }
        MerchantMenu merchantMenu = new MerchantMenu();
        request.setId(null);
        BeanUtils.copyProperties(request, merchantMenu);
        merchantMenu.setMerId(user.getMerId());
        boolean save = save(merchantMenu);
        if (save) {
            redisUtil.delete(cacheKey);
        }
        return save;
    }

    @Override
    public Boolean deleteById(Integer id) {
        MerchantAdmin user = SecurityUtil.getMerLoginUserVo().getUser();
        String cacheKey = CACHE_LIST_KEY + user.getMerId();
        MerchantMenu merchantMenu = getInfoById(id);
        if(!user.getMerId().equals(merchantMenu.getMerId())){
            throw new HhException("商户异常，删除失败！");
        }
        if(!Constants.PLATFORM_MER_ID.equals(user.getMerId())){
            throw new HhException("您没有权限操作");
        }
        merchantMenu.setIsDelte(true);
        if (merchantMenu.getMenuType().equals("A")) {
            boolean update = updateById(merchantMenu);
            if (update) {
                redisUtil.delete(cacheKey);
            }
            return update;
        }
        List<MerchantMenu> childList = findAllChildListByPid(id);
        if (CollUtil.isEmpty(childList)) {
            boolean update = updateById(merchantMenu);
            if (update) {
                redisUtil.delete(cacheKey);
            }
            return update;
        }
        childList.forEach(e -> e.setIsDelte(true));
        childList.add(merchantMenu);
        boolean updateBatch = updateBatchById(childList);
        if (updateBatch) {
            redisUtil.delete(cacheKey);
        }
        return updateBatch;
    }

    @Override
    public Boolean edit(SystemMenuRequest request) {
        MerchantAdmin user = SecurityUtil.getMerLoginUserVo().getUser();
        String cacheKey = CACHE_LIST_KEY + user.getMerId();
        if (ObjectUtil.isNull(request.getId())) {
            throw new HhException("系统菜单id不能为空");
        }
        if (request.getMenuType().equals("C") && StrUtil.isEmpty(request.getComponent())) {
            throw new HhException("菜单类型的组件路径不能为空");
        }
        if (request.getMenuType().equals("A") && StrUtil.isEmpty(request.getPerms())) {
            throw new HhException("按钮类型的权限表示不能为空");
        }

        MerchantMenu byId = getById(request.getId());
        if(!user.getMerId().equals(byId.getMerId())){
            throw new HhException("商户异常，修改失败！");
        }
        if(!Constants.PLATFORM_MER_ID.equals(user.getMerId())){
            throw new HhException("您没有权限操作");
        }
        MerchantMenu merchantMenu = new MerchantMenu();
        BeanUtils.copyProperties(request, merchantMenu);
        boolean update = updateById(merchantMenu);
        if (update) {
            redisUtil.delete(cacheKey);
        }
        return update;
    }

    @Override
    public MerchantMenu getInfo(Integer id) {
        MerchantMenu merchantMenu = getInfoById(id);
        merchantMenu.setIsDelte(null);
        merchantMenu.setCreateTime(null);
        merchantMenu.setUpdateTime(null);
        return merchantMenu;
    }

    @Override
    public Boolean updateShowStatus(Integer id) {
        MerchantAdmin user = SecurityUtil.getMerLoginUserVo().getUser();
        String cacheKey = CACHE_LIST_KEY + user.getMerId();
        MerchantMenu merchantMenu = getInfoById(id);
        if(!user.getMerId().equals(merchantMenu.getMerId())){
            throw new HhException("商户异常，修改失败！");
        }
        merchantMenu.setIsShow(!merchantMenu.getIsShow());
        boolean update = updateById(merchantMenu);
        if (update) {
            redisUtil.delete(cacheKey);
        }
        return update;
    }

    @Override
    public List<MenuCheckVo> getCacheTree() {
        MerchantAdmin user = SecurityUtil.getMerLoginUserVo().getUser();
        List<MerchantMenu> menuList = getCacheList(user.getMerId());
        List<MenuCheckVo> voList = menuList.stream().map(e -> {
            MenuCheckVo menuCheckVo = new MenuCheckVo();
            BeanUtils.copyProperties(e, menuCheckVo);
            return menuCheckVo;
        }).collect(Collectors.toList());
        MenuCheckTree menuTree = new MenuCheckTree(voList);
        return menuTree.buildTree();
    }

    @Override
    public List<MerchantMenu> findAllCatalogue(String merId) {
        LambdaQueryWrapper<MerchantMenu> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerchantMenu::getMerId,merId);
        lqw.eq(MerchantMenu::getIsDelte, false);
        lqw.eq(MerchantMenu::getIsShow, true);
        lqw.ne(MerchantMenu::getMenuType, "A");
        return dao.selectList(lqw);
    }

    @Override
    public List<MerchantMenu> getMenusByUserId(Integer userId) {
        return dao.getMenusByUserId(userId);
    }

    /**
     * 初始化商户菜单
     * @param merId
     * @return
     */
    @Override
    public Boolean initMenus(String merId) {
        List<MerchantMenuInit> merchantMenuInits = merchantMenuInitDao.selectList(null);

        for (MerchantMenuInit merchantMenuInit : merchantMenuInits) {
            if(merchantMenuInit.getPid() == 0){
                MerchantMenu merchantMenu = new MerchantMenu();
                BeanUtil.copyProperties(merchantMenuInit,merchantMenu);
                merchantMenu.setMerId(merId);
                save(merchantMenu);
                Integer pid = merchantMenu.getId();
                recursionSaveItems(pid,merchantMenuInit.getId(),merId);
            }
        }

        return Boolean.TRUE;
    }

    private void recursionSaveItems(Integer pid,Integer id,String merId) {
        List<MerchantMenuInit> list = merchantMenuInitDao.getItemsByPid(id);

        if(list.size() > 0){

            for (MerchantMenuInit merchantMenuInit : list) {
                MerchantMenu merchantMenu = new MerchantMenu();
                BeanUtil.copyProperties(merchantMenuInit,merchantMenu);
                merchantMenu.setMerId(merId);
                merchantMenu.setPid(pid);
                save(merchantMenu);
                Integer pid01 = merchantMenu.getId();

                List<MerchantMenuInit> list01 = merchantMenuInitDao.getItemsByPid(merchantMenuInit.getId());
                if(list01.size() > 0){
                    for (MerchantMenuInit merchantMenuInit01 : list01) {
                        MerchantMenu merchantMenu01 = new MerchantMenu();
                        BeanUtil.copyProperties(merchantMenuInit01,merchantMenu01);
                        merchantMenu01.setMerId(merId);
                        merchantMenu01.setPid(pid01);
                        save(merchantMenu01);
                        Integer pid02 = merchantMenu01.getId();
                        List<MerchantMenuInit> list02 = merchantMenuInitDao.getItemsByPid(merchantMenuInit01.getId());
                        if(list02.size() > 0){
                            for (MerchantMenuInit merchantMenuInit02 : list02) {
                                MerchantMenu merchantMenu02 = new MerchantMenu();
                                BeanUtil.copyProperties(merchantMenuInit02,merchantMenu02);
                                merchantMenu02.setMerId(merId);
                                merchantMenu02.setPid(pid02);
                                save(merchantMenu02);
                                Integer pid03 = merchantMenu02.getId();
                                List<MerchantMenuInit> list03 = merchantMenuInitDao.getItemsByPid(merchantMenuInit02.getId());
                                if(list03.size() > 0){
                                    for (MerchantMenuInit merchantMenuInit03 : list03) {
                                        MerchantMenu merchantMenu03 = new MerchantMenu();
                                        BeanUtil.copyProperties(merchantMenuInit03,merchantMenu03);
                                        merchantMenu03.setMerId(merId);
                                        merchantMenu03.setPid(pid03);
                                        save(merchantMenu03);
                                        Integer pid04 = merchantMenu03.getId();
                                        List<MerchantMenuInit> list04 = merchantMenuInitDao.getItemsByPid(merchantMenuInit03.getId());
                                        if(list04.size() > 0){
                                            for (MerchantMenuInit merchantMenuInit04 : list04) {
                                                MerchantMenu merchantMenu04 = new MerchantMenu();
                                                BeanUtil.copyProperties(merchantMenuInit04,merchantMenu04);
                                                merchantMenu04.setMerId(merId);
                                                merchantMenu04.setPid(pid04);
                                                save(merchantMenu04);
                                                Integer pid05 = merchantMenu04.getId();
                                                List<MerchantMenuInit> list05 = merchantMenuInitDao.getItemsByPid(merchantMenuInit04.getId());
                                                if(list05.size() > 0){
                                                    for (MerchantMenuInit merchantMenuInit05 : list05) {
                                                        MerchantMenu merchantMenu05 = new MerchantMenu();
                                                        BeanUtil.copyProperties(merchantMenuInit05,merchantMenu05);
                                                        merchantMenu05.setMerId(merId);
                                                        merchantMenu05.setPid(pid05);
                                                        save(merchantMenu05);
                                                        Integer pid06 = merchantMenu05.getId();
                                                    }
                                                }
                                            }
                                        }

                                    }
                                }
                            }
                        }
                    }
                }
            }
        }else {
            return;
        }
    }

    /**
     * 根据菜单id获取所有下级对象
     * @param pid 菜单id
     * @return List<SystemMenu>
     */
    private List<MerchantMenu> findAllChildListByPid(Integer pid) {
        LambdaQueryWrapper<MerchantMenu> lqw = Wrappers.lambdaQuery();
        lqw.eq(MerchantMenu::getPid, pid);
        lqw.eq(MerchantMenu::getIsDelte, false);
        return dao.selectList(lqw);
    }

    /**
     * 获取详细信息
     * @param id 菜单id
     * @return SystemMenu
     */
    private MerchantMenu getInfoById(Integer id) {
        MerchantMenu merchantMenu = getById(id);
        if (ObjectUtil.isNull(merchantMenu) || merchantMenu.getIsDelte()) {
            throw new HhException("系统菜单不存在");
        }
        return merchantMenu;
    }
}
